package com.incar.chuxing.utils.ble.utils;

import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;

/**
 * ArrayUtil,一些基于byte数组的操作方法集
 * <p>
 * <p/>
 * <p>
 * Author By:
 * <p>
 * Created Date:
 */

public class ArrayUtil {

    /**
     * 查找并替换指定byte数组
     *
     * @param org        of type byte[] 原数组
     * @param search     of type byte[] 要查找的数组
     * @param replace    of type byte[] 要替换的数组
     * @param startIndex of type int 开始搜索索引
     * @return byte[] 返回新的数组
     * @throws UnsupportedEncodingException when
     */

    public static byte[] arrayReplace(byte[] org, byte[] search,
                                      byte[] replace, int startIndex) throws UnsupportedEncodingException {

        int index = indexOf(org, search, startIndex);

        if (index != -1) {

            int newLength = org.length + replace.length - search.length;

            byte[] newByte = new byte[newLength];

            System.arraycopy(org, 0, newByte, 0, index);

            System.arraycopy(replace, 0, newByte, index, replace.length);

            System.arraycopy(org, index + search.length, newByte, index
                    + replace.length, org.length - index - search.length);

            int newStart = index + replace.length;

            // String newstr = new String(newByte, “GBK”);

            // System.out.println(newstr);

            if ((newByte.length - newStart) > replace.length) {

                return arrayReplace(newByte, search, replace, newStart);

            }

            return newByte;

        } else {

            return org;

        }

    }

    /**
     * 数组的元素替换
     *
     * @param org        原数组
     * @param content    替换的内容
     * @param startIndex 从第内位开始
     */
    public static void arrayReplace2(byte[] org, byte[] content, int startIndex) {
        if (content != null && org != null) {
            int len = content.length;
            if (startIndex + len <= org.length) {
                for (int i = 0; i < len; i++) {
                    org[startIndex + i] = content[i];
                }
            }
        }

    }

    /**
     * 合并两数组
     *
     * @param org of type byte[] 原数组
     * @param to  合并一个byte[]
     * @return 合并的数据
     */

    public static byte[] append(byte[] org, byte[] to) {

        byte[] newByte = new byte[org.length + to.length];

        System.arraycopy(org, 0, newByte, 0, org.length);

        System.arraycopy(to, 0, newByte, org.length, to.length);

        return newByte;

    }

    /**
     * 合并一个数组和一个byte
     *
     * @param org of type byte[] 原数组
     * @param to  合并一个byte
     * @return 合并的数据
     */

    public static byte[] append(byte[] org, byte to) {

        byte[] newByte = new byte[org.length + 1];

        System.arraycopy(org, 0, newByte, 0, org.length);

        newByte[org.length] = to;

        return newByte;

    }

    /**
     * @param org    of type byte[] 原数组
     * @param from   起始点
     * @param append 要合并的数据
     */

    public static void append(byte[] org, int from, byte[] append) {

        System.arraycopy(append, 0, org, from, append.length);

    }

    /**
     * 多个byte[] 拼接
     *
     * @param contents
     * @return
     */
    public static byte[] byteMerger(byte[]... contents) {
        int len = 0;
        for (byte[] bs : contents) {
            if (bs == null) {
                continue;
            }
            len += bs.length;
        }
        byte[] all = new byte[len];
        int index = 0;
        for (byte[] org : contents) {
            if (org == null) {
                continue;
            }
            int tempLen = org.length;
            System.arraycopy(org, 0, all, index, tempLen);
            index += tempLen;
        }

        return all;
    }

    /**
     * 从一个数组中截取一个数组
     *
     * @param original of type byte[] 原数组
     * @param from     起始点
     * @param to       结束点
     * @return 返回copy的数组
     */

    public static byte[] copyOfRange(byte[] original, int from, int to) {

        int newLength = to - from;

        if (newLength < 0)
            return null;
        // throw new IllegalArgumentException(from + ">" + to);

        if (newLength == 0) {
            return null;
        }
        byte[] copy = new byte[newLength];

        System.arraycopy(original, from, copy, 0,

                Math.min(original.length - from, newLength));

        return copy;

    }

    /**
     * 字符转byte[]
     *
     * @param encode
     * @param chars
     * @return
     */
    public static byte[] char2byte(String encode, char... chars) {

        Charset cs = Charset.forName(encode);

        CharBuffer cb = CharBuffer.allocate(chars.length);

        cb.put(chars);

        cb.flip();

        ByteBuffer bb = cs.encode(cb);

        return bb.array();

    }

    /**
     * 查找指定数组的起始索引
     *
     * @param org    of type byte[] 原数组
     * @param search of type byte[] 要查找的数组
     * @return int 返回索引
     */

    public static int indexOf(byte[] org, byte[] search) {

        return indexOf(org, search, 0);

    }

    /**
     * 查找指定数组的起始索引
     *
     * @param org        of type byte[] 原数组
     * @param search     of type byte[] 要查找的数组
     * @param startIndex 起始索引
     * @return int 返回索引
     */

    public static int indexOf(byte[] org, byte[] search, int startIndex) {

        KMPMatcher kmpMatcher = new KMPMatcher();

        kmpMatcher.computeFailure4Byte(search);

        return kmpMatcher.indexOf(org, startIndex);

        // return com.alibaba.common.lang.ArrayUtil.indexOf(org, search);

    }

    /**
     * 查找指定数组的最后一次出现起始索引
     *
     * @param org    of type byte[] 原数组
     * @param search of type byte[] 要查找的数组
     * @return int 返回索引
     */

    public static int lastIndexOf(byte[] org, byte[] search) {

        return lastIndexOf(org, search, 0);

    }

    /**
     * 查找指定数组的最后一次出现起始索引
     *
     * @param org       of type byte[] 原数组
     * @param search    of type byte[] 要查找的数组
     * @param fromIndex 起始索引
     * @return int 返回索引
     */

    public static int lastIndexOf(byte[] org, byte[] search, int fromIndex) {

        KMPMatcher kmpMatcher = new KMPMatcher();

        kmpMatcher.computeFailure4Byte(search);

        return kmpMatcher.lastIndexOf(org, fromIndex);

    }

    /**
     * KMP算法类
     * <p>
     * <p/>
     * <p>
     * Created on 2011-1-3
     */

    public static void main(String[] args) {

        try {

            byte[] org = "kadeddddddfdsaddghhdjddddddddadedcfdededghkk"
                    .getBytes("GBK");

            byte[] search = "kk".getBytes("GBK");

            int last = lastIndexOf(org, search, 19);

            long t1 = 0;

            long t2 = 0;

            int f1 = 0;

            int f2 = 0;

            for (int i = 0; i < 10000; i++) {

                long s1 = System.nanoTime();

                f1 = indexOf(org, search, 0);

                // ArrayUtils.addAll(org, org);

                long s2 = System.nanoTime();
                // ArrayUtil.append(org, org);
                f2 = ArrayUtil.indexOf(org, search);

                long s3 = System.nanoTime();

                t1 = t1 + (s2 - s1);

                t2 = t2 + (s3 - s2);

            }

            System.out.println("kmp=" + t1 / 10000 + ",ali=" + t2 / 10000);

            System.out.printf("f1=" + f1 + ",f2=" + f2);

        } catch (UnsupportedEncodingException e) {

            e.printStackTrace();

        }

    }

    public static byte[] getBytes(short s, boolean asc) {
        byte[] buf = new byte[2];
        if (asc)// 高位在前
            for (int i = buf.length - 1; i >= 0; i--) {
                buf[i] = (byte) (s & 0x00ff);
                s >>= 8;
            }
        else
            for (int i = 0; i < buf.length; i++) {
                buf[i] = (byte) (s & 0x00ff);
                s >>= 8;
            }
        return buf;
    }

    public static byte[] getBytes(int s, boolean asc) {
        byte[] buf = new byte[4];
        if (asc)// 高位在前
            for (int i = buf.length - 1; i >= 0; i--) {
                buf[i] = (byte) (s & 0x000000ff);
                s >>= 8;
            }
        else
            for (int i = 0; i < buf.length; i++) {
                buf[i] = (byte) (s & 0x000000ff);
                s >>= 8;
            }
        return buf;
    }

    public static byte[] getBytes(long s, boolean asc) {
        byte[] buf = new byte[8];
        if (asc)
            for (int i = buf.length - 1; i >= 0; i--) {
                buf[i] = (byte) (s & 0x00000000000000ff);
                s >>= 8;
            }
        else
            for (int i = 0; i < buf.length; i++) {
                buf[i] = (byte) (s & 0x00000000000000ff);
                s >>= 8;
            }
        return buf;
    }

    public static short getShort(byte[] buf, boolean asc) {
        if (buf == null) {
            throw new IllegalArgumentException("byte array is null!");
        }
        if (buf.length > 2) {
            throw new IllegalArgumentException("byte array size > 2 !");
        }
        short r = 0;
        if (asc)
            for (int i = buf.length - 1; i >= 0; i--) {
                r <<= 8;
                r |= (buf[i] & 0x00ff);
            }
        else
            for (int i = 0; i < buf.length; i++) {
                r <<= 8;
                r |= (buf[i] & 0x00ff);
            }
        return r;
    }

    public static int getInt(byte[] buf, boolean asc) {
        if (buf == null) {
            throw new IllegalArgumentException("byte array is null!");
        }
        if (buf.length > 4) {
            throw new IllegalArgumentException("byte array size > 4 !");
        }
        int r = 0;
        if (asc)
            for (int i = buf.length - 1; i >= 0; i--) {
                r <<= 8;
                r |= (buf[i] & 0x000000ff);
            }
        else
            for (int i = 0; i < buf.length; i++) {
                r <<= 8;
                r |= (buf[i] & 0x000000ff);
            }
        return r;
    }

    public static long getLong(byte[] buf, boolean asc) {
        if (buf == null) {
            throw new IllegalArgumentException("byte array is null!");
        }
        if (buf.length > 8) {
            throw new IllegalArgumentException("byte array size > 8 !");
        }
        long r = 0;
        if (asc)
            for (int i = buf.length - 1; i >= 0; i--) {
                r <<= 8;
                r |= (buf[i] & 0x00000000000000ff);
            }
        else
            for (int i = 0; i < buf.length; i++) {
                r <<= 8;
                r |= (buf[i] & 0x00000000000000ff);
            }
        return r;
    }

}
